Optimizing SmileBasic code
There is a lot of interest in how to make Petit Computer programs run faster, so this page is for a collection of optimizations. Note that generally, optimizations are very bad for readability. Putting too much emphasis on optimization is a common beginners' mistake, because the benefits of readability are not as apparent or compelling until one has had more programming experience. Readability is important for maintainance (if a new bug is discovered, it will help greatly in locating the source(s) of the bug and fixing it without breaking something else), for expandability (if a new feature is to be added, readability makes it much easier to figure out how and where to add it), and for robustness (any kind of tinkering with highly-optimized code is more likely to cause a bug that's more difficult to diagnose and fix). The optimizations below will generally give an improvement of only a few percent at best. As a contribution to the programming community, readability is much more valuable than a few percent speed gain. But, since many contributions are not for the programming community to analyze and learn from, but instead are for the game-playing community to play, there is value in having a list of optimizations for use when the design is finalized and the bugs are fixed and the author doesn't care if others want to learn from or tinker with the code. One final caveat: Petit Computer is a sophisticated piece of software. It has many subsystems, with many interactions between them, some quite subtle. There may be conditions where some of the tips mentioned below do not improve running speed, they may indeed slow things down. Now for the actual list of optimizations (unless otherwise noted, these optimizations have only been observed on a 3DS running SmileBasic V2): * GOSUB takes time. Copies of the code in-line will run faster. * FOR loops take time. If a section of code is to be repeated a fixed number of times, copying the code will run faster than looping the code. * NEXT is faster if it does not have a variable name. * If the branches of an IF command are executed with 50/50 probability, it is faster overall to have the shorter branch be THEN and the longer branch be ELSE; if the branches take an equal amount of time, it is faster to have the more commonly executed branch be THEN and the less commonly executed branch be ELSE. * Blank lines take time, comments take more time, and longer comments take yet more time. * Removing unneeded spaces speeds things up (e.g. instead of FOR I=0 TO 10, use FOR I=0TO 10). * Having commands on successive lines is faster than using :, the command separator, but faster yet is having commands follow one another without a command separator (e.g. A=B PRINT A or A=0B=0). * Remove leading '0's from integer literals (e.g. instead of H=100T=010U=001, use H=100T=10U=1). * Shorter variable names are faster. * Shorter labels are faster. * Accessing a scalar variable is faster than accessing an array entry. If a particular array entry occurs in many expressions, the time it takes to copy it to a scalar variable may be more than made up for by the speed increase in the following references to the value. * X*X is faster than POW(X,2). However, if X is replaced with a complicated expression that takes more time to evaluate, having it appear once in with POW may be faster than having it appear twice with multiplication. * An integer numerical literal is faster without a decimal point following it, and a numerical literal without a decimal point is faster than reading a numerical variable. * If you need a string representation of an integer numerical value, and you're not particular about the details of that representation, HEX$ is faster than STR$. Indexing a string array is faster than both (though this is subject to both the string memory limitation and the array memory limitation). * When you need to GOTO or GOSUB a label that depends on the value of a variable, it is quicker to use the ON ... GOTO and ON ... GOSUB commands rather than use GOTO or GOSUB with a string array. * Using the empty string literal ("") is faster than referencing a string variable that contains the empty string. * A FOR that takes the same number of iterations without a STEP is faster than one with a STEP (e.g. FOR A=1TO 10 is faster than FOR A=10TO 100STEP 10), and a positive STEP value is faster than a negative STEP value (e.g. FOR A=10TO 100STEP 10 is faster than FOR A=100TO 10STEP-10). * The expression after TO and the expression after STEP are evaluated each loop of the FOR. So, for example, consider the difference between FOR I=1 TO 100 and FOR I=1 TO 10*10. The expression 10*10 takes more time than the expression 100... and the second FOR takes more time than the first, by one hundred times that much. * Having PNLTYPE "OFF" will speed up code. Except, it seems, under certain conditions where sprites are used, and WAIT and/or VSYNC are used. * The quote character (") to close a string literal is optional if it is at the end of a line: surprisingly, it is faster to include the final quote than it is to omit it. * Where you have IF (condition1) AND (condition2) THEN..., it can sometimes be faster to have IF (condition1) THEN IF (condition2) THEN.... Note that this is not always faster, sometimes it is slower; it is most effective when condition1 is rarely true, and/or condition2 takes a long time to compute. Also note that if there are ELSE branches, care will need to be taken, and this may make AND the faster option. * IF condition GOTO@label is generally faster than IF condition THEN@label, and both are faster than IF condition THEN GOTO@label. * ! before a value is faster than !=0 after it. !! before a value is faster than 0 after it. Note that ! has a higher precedence than != and , so extra parentheses may be necessary, which then make the expression slower. * Rearranging expressions may give a very slight speed-up. In general, it seems if you put the higher-precedence operators first, the expression will get evaluated a tiny bit faster. * Finally, it is worth noting that ? is not faster than PRINT. Apparently, the code gets tokenized before it gets run. Category:Resources Category:System Guides Category:Programming Concepts